1 Exploratory analysis

1.1 Selection des questionnaires

Au tout début on a 870 lignes et 381 IDs.

Après avoir exclu 4 lignes à cause de missing ID, on descend à 866 questionnaires et 380 IDs (l’ID “valeur manquante” n’est plus comptabilisé, c’est pour ça qu’on “perd” un ID).

Sachant que 380x2=760on a 106 entrées de trop.
On retrouve 16 questionnaires completement vides, qu’on peut exclure ce qui nous donne 850 questionnaires et 379 IDs uniques.

On est tjrs très loin de notre objectif de environ 760 questionnaires (758 maintenant qu’on a 379 IDs).

Donc, on a forcement des IDs pour lesquels on a >2 entrées. Voyons de les mettre en evidence.

data %>% 
    group_by(id) %>% 
    summarise(n=n()) %>%
    arrange(desc(n)) %>%
    datatable(options = list(pageLength = 10,
                             #dom = 't',
                             scrollX = TRUE,
                             width = "auto",
                             scrollX = T
                             ))
problematic_IDs = data %>% group_by(id) %>% summarise(n=n()) %>% filter(n>2) %>% nrow


Comme tu peux le voir on semble avoir 48 IDs presents au moins 3 fois.
Creusons plus loin pour voir si on identifie un groupe d’IDs problematique. Théoriquement, si les gens avaient respecté les régles pour la création de l’identifiant anonyme, l’identifiant devrait suivre le pattern suivant: 1 chiffre - 2 lettres - 2 chiffres.

Voyons pour combien de lignes ce pattern est respecté:

str_detect(data$id, "[:digit:]{1}[:alpha:]{2}[:digit:]{2}") %>% 
    table %>%
    pander
FALSE TRUE
44 806

Cela nous dit que même si on regarde seulement les gens qui ont respecté la procedure pour la création des IDs, on à tjrs des lignes de trop. D’abord, regardons les entrés des gens qui ont tapé un ID au pif.

data %>% 
    filter(!str_detect(id, "[:digit:]{1}[:alpha:]{2}[:digit:]{2}")) %>%
    arrange(id) %>% 
    datatable(options = list(pageLength = 10,
                             #dom = 't',
                             scrollX = TRUE,
                             width = "auto",
                             scrollX = T
                             ))


Néanmoins, s’ils ont utilisé 2 fois le même identifiant aberrant on pourra quand même les apparier. Voyons donc les IDs qui apparaissent >2 fois. Les IDs aberrants qui apparaissent 2 fois on peut les utiliser, les IDs qui apparaissent qu’une seule fois, idem, on peut les garder pour la partie descriptive (carrement ils ne sera pas possible de les utiliser pour la comparaison avant-après).

data %>% 
    filter(!str_detect(id, "[:digit:]{1}[:alpha:]{2}[:digit:]{2}")) %>%
    group_by(id) %>%
    summarise(n=n()) %>% 
    arrange(desc(n)) %>%
    datatable(options = list(pageLength = 10,
                             #dom = 't',
                             scrollX = TRUE,
                             width = "auto",
                             scrollX = T
                             ))

On voit que le seul ID problematique parmi les aberrants est “12345”.
Est-ce que la filière pourrait nous aider? Voyons.

data %>% 
    filter(id=="12345") %>%
    datatable(options = list(pageLength = 10,
                             #dom = 't',
                             scrollX = TRUE,
                             width = "auto",
                             scrollX = T
                             ))

On semble avoir 1 IDE et 1 MG, qui ont un doublon de “2ème test”. Si on regarde avec attention la ligne 3 et 4 sont identiques, avec une “filière” différente.
Si la ligne 3 et 4 étaient par exemple “IDE” et la ligne 5 et 6 étaient “medecine generale” on aurait identifié des doublons –> problème résolu. Mais dans ce cas on a des doublons ET 2 personnes qui ont rentré 2 fois le “2ème test” en changeant aussi de filière. Ou Il est donc impossible de rattacher ces questionnaires à un “test 1”. Ce qui est très très bizarre, est que les lignes 3 et 5 sont IDENTIQUES aux lignes 4 et 6. Ce qu’on peut faire, est prendre la moyenne des lignes 3-5 et 4-6. Le même approche nous sera utile pour gérer les IDs non aberrants doublons qui sont les suivants:

data %>% 
    filter(str_detect(id, "[:digit:]{1}[:alpha:]{2}[:digit:]{2}")) %>%
    group_by(id) %>%
    mutate(n=n()) %>% 
   filter(n>2) %>%
    relocate(n, .after = id) %>% 
    arrange(desc(n)) %>% 
    datatable(options = list(pageLength = 10,
                             #dom = 't',
                             scrollX = TRUE,
                             width = "auto",
                             scrollX = T
                             ))
data = data%>%
     group_by(id, test, filiere) %>%
     summarise(across(s1q1:last_col(), ~mean(., na.rm = TRUE)), .groups = "drop")

Vu que “ID” ne suffit pour identifier uniquement les lignes, si on prend “ID” + “test” + “filiere” et on fait la moyenne des lignes ambigues on devrait s’en sortir pas mal. Cela nous laisse avec 776 questionnaires.
Bon, on sait dejà qu’on a des IDs qui apparaissent trop souvent mais si on prend ID-filiere, est-ce que maintenant on a max 2 lignes par couple ID-filiere?

data %>% 
    group_by(id,filiere) %>%
    summarise(n=n()) %>% 
    arrange(desc(n)) %>%
    datatable(options = list(pageLength = 10,
                             #dom = 't',
                             scrollX = TRUE,
                             width = "auto",
                             scrollX = T
                             ))
## `summarise()` has grouped output by 'id'. You can override using the `.groups`
## argument.


Oui! Nous avons maintenant 413 identité uniques données par ID+FILIERE. Vu qu’on a besoin de “filière” pour identifier les gens, on va esclure les lignes où “filière” n’est pas renseigné.

filiere_na = data %>% filter(is.na(filiere)) %>% nrow()

# REMOVING MISSING "filiere" rows
data = data %>% filter(!is.na(filiere))

# How many questionnaires left?
questionnaires = nrow(data)
# How many unique identifties?
ids = data %>% distinct(id,filiere) %>% nrow

On exclu donc 9 lignes car valeur manquante. On est maintenant à 767 questionnaires pour 413 identités. Voyons combien de gens on peut apparier.


data %>% 
    group_by(id,filiere) %>%
    summarise(n=n(), .groups="drop") %>% 
    arrange(desc(n)) %$%
    table(n) %>%
    pander(caption = "Nb questionnaires appariés et non")
Nb questionnaires appariés et non
1 2
59 354


Flowchart inclusion questionnaires

Figure 1.1: Flowchart inclusion questionnaires


#########

1.2 Nb et repartition sujets participants

data %>% distinct(id,filiere) %$% 
    table(filiere) %>% 
    as.data.frame() %>% 
    mutate("%" = round(Freq/sum(Freq)*100, 2)) %>% 
    adorn_totals() %>% 
    pander(caption = "**Repartition sujets par filière**")
Repartition sujets par filière
filiere Freq %
IDE 166 40.19
maieutique 25 6.05
medecine generale 97 23.49
MKE 48 11.62
orthophonie 28 6.78
pharmacie 49 11.86
Total 413 99.99

1.3 Missing values

Voyons sur tout l’ensemble de tests, combien de données manquantes on a. Ce sont des “vraies” données manquantes OU des “NSP” qui n’était pas pertinents pour la question et vraisemblablement pris pour des “Ne sait pas”.

table(data$na_counts) %>% 
    as.data.frame() %>% 
    mutate("%" = round(Freq/sum(Freq)*100, 2)) %>% 
    rename("Nb missing values" = Var1) %>% 
    pander(caption = "**Nb de valeurs manquantes par questionnaire**")
Nb de valeurs manquantes par questionnaire
Nb missing values Freq %
0 688 89.7
0.333333333333333 1 0.13
0.5 7 0.91
1 45 5.87
2 16 2.09
3 3 0.39
4 1 0.13
5 5 0.65
6 1 0.13

On voit que les tests sont bien complets globalement sauf 16 questionnaires qui sont complétement vides. Ils sont des doublons dus à des enregistrements vides.



1.3.1 Missing values par filière

On peut voir que la repartition des valeurs manquantes par filière est en ligne avec la repartition des sujets par filière. Donc il n’y a pas une filière qui a laissé le questionnaire “plus vide” que les autres.

data %>%
  group_by(filiere) %>%
  summarise(Freq = sum(na_counts)) %>%
  mutate("%" = round(Freq / sum(Freq) * 100, 2)) %>%
    adorn_totals() %>% 
  pander(caption = "**Valeurs manquantes par filière**", align = "center")
Valeurs manquantes par filière
filiere Freq %
IDE 59.83 47.93
maieutique 5 4.01
medecine generale 30 24.03
MKE 9 7.21
orthophonie 5 4.01
pharmacie 16 12.82
Total 124.8 100

!!!!!! Quelque chose ne va pas, on a 379 sujets et 800+ questionnaires (on devrait en avoir au max 379*2). Dans le tableau suivant on voit qu’on a 199 sujets avec au moins 3 entrées (et j’ai déjà exclu les 16 dont je parlais avant).

x <- data %>%
  group_by(id, filiere) %>%
  summarise(n = n()) %>%
  arrange(desc(n)) %>%
  filter(n > 2) %>%
  pull(id) 

data %>%
    filter(id %in% x) %>%
    arrange(id, filiere, test) %>%
    datatable(options = list(pageLength = 10,
                             #dom = 't',
                             scrollX = TRUE,
                             width = "auto",
                             scrollX = T
                             )
              ) 

Les entrées supplementaires ne sont pas des “doublons”, les valeurs ne sont pas les mêmes. Je vais donc prendre la moyenne de ces valeurs. Ci dessous le résultat, on est à 766 lignes alor que notre max theorique est 758. Il y a forcement des gens qui se sont enregistrés avec plus qu’un ID (j’ai renommé la variable “A1”).
Ca ne m’inquiète pas pour les tests appariés, je ne pense pas que des gens ont 2*2 tests appariés mais je controllerai.

data %>% 
    group_by(id,test,filiere) %>% 
    summarise(across(s1q1:s7q2,mean,na.rm=T)) %>% 
    mutate(na_counts = rowSums(across(s1q1:s7q2, is.na))) %>% 
    datatable(options = list(pageLength = 10,
                             #dom = 't',
                             scrollX = TRUE,
                             width = "auto",
                             scrollX = T
                             )
              )
## `summarise()` has grouped output by 'id', 'test'. You can override using the
## `.groups` argument.



2 Tests appariés

# DF with id-filiere-pre-post pour les tests stat
test_data <- data %>%
  group_by(id, filiere, test) %>%
  summarise(mean_score = mean(c_across(s1q1:s7q2), na.rm = T)) %>%
  pivot_wider(names_from = "test", values_from = "mean_score") %>%
    filter(!is.na(post),!is.na(pre)) %>% distinct
## `summarise()` has grouped output by 'id', 'filiere'. You can override using the
## `.groups` argument.
# paired cases by filiere
test_data %$% 
    table(filiere) %>% 
    as.data.frame() %>% 
    mutate("%" = round(Freq/sum(Freq)*100, 2)) %>% 
    adorn_totals() %>% 
    pander(caption = "Cas appariés par filière")
Cas appariés par filière
filiere Freq %
IDE 135 38.14
maieutique 24 6.78
medecine generale 88 24.86
MKE 38 10.73
orthophonie 25 7.06
pharmacie 44 12.43
Total 354 100

Pour ces pourcentages les denominateur est “total de tests appariés” et non le “nombre total de tests. Donc, les IDE, representent 38.14% des tests appariés disponibles.

Mais, il y a carrement plus d’IDE que les autres filières! Oui, bien sur. Voyons

3 Tests stat

# PRE vs POST, toutes filieres confondues
t.test(test_data$post,test_data$pre, paired=T)
## 
##  Paired t-test
## 
## data:  test_data$post and test_data$pre
## t = 15.96, df = 353, p-value < 2.2e-16
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
##  0.5796475 0.7425832
## sample estimates:
## mean of the differences 
##               0.6611153
# PRE vs POST, filiere par filiere 
t.test(test_data$post[test_data$filiere=="IDE"],test_data$pre[test_data$filiere=="IDE"], paired=T)
## 
##  Paired t-test
## 
## data:  test_data$post[test_data$filiere == "IDE"] and test_data$pre[test_data$filiere == "IDE"]
## t = 9.0251, df = 134, p-value = 1.68e-15
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
##  0.4998955 0.7804887
## sample estimates:
## mean of the differences 
##               0.6401921
LS0tDQojIEdlbmVyYWwgSW5mb3JtYXRpb24gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCnRpdGxlOiAgICAiVGjDqHNlIC0gUmFjaGVsIEZyw6lib3VyZyINCnN1YnRpdGxlOiAiQ29tcGFyYWlzb24gYXZhbnQtYXByw6hzIG5pdmVhdSBpbnRlcmRpc2NpcGxpbmFyaXTDqSBjaGV6IGxlcyBwcm8gZGUgc2FudMOpIg0KYXV0aG9yOiAgICJGcmFuY2VzY28gTU9OVEkiDQpkYXRlOiAgICAgImByIFN5cy50aW1lKClgIiAjIEF1dG9tYXRpYyBkYXRlIGFuZCB0aW1lDQojIERvY3VtZW50IEZvcm1hdCBhbmQgQXBwZWFyYW5jZSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgdHlwZSA/aHRtbF9kb2N1bWVudCBmb3IgbW9yZSBkZXRhaWxzDQpvdXRwdXQ6DQogICAgYm9va2Rvd246Omh0bWxfZG9jdW1lbnQyOiANCiAgICAgICAgdG9jOiAgICAgICAgIHllcyAgICAgICAgIyBUYWJsZSBvZiBjb250ZW50cyAodG9jKTogeWVzIG5vDQogICAgICAgIHRvY19mbG9hdDogICB5ZXMgICAgICAgICMgeWVzIG5vDQogICAgICAgIHRvY19kZXB0aDogICA1ICAgICAgICAgICAgICAjIDEgMiAzIDQgNQ0KICAgICAgICBoaWdobGlnaHQgOiBweWdtZW50cyAgICAgICMgZGVmYXVsdCB0YW5nbyBrYXRlIG1vbm9jaHJvbWUgZXNwcmVzc28gcHlnbWVudHMuLi4NCiAgICAgICAgaGlnaGxpZ2h0X2Rvd25saXQgOiBGQUxTRSAgICAgICMgVFJVRSB0byB1c2UgdGhlIGRvd25saXQgcGFja2FnZSBhcyBzeW50YXggaGlnaGxpZ2h0IGVuZ2luZSB0byBoaWdobGlnaHQgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGlubGluZSBjb2RlIGFuZCBSIGNvZGUgY2h1bmtzIChpbmNsdWRpbmcgcHJvdmlkaW5nIGh5cGVybGlua3MgdG8gZnVuY3Rpb24gDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGRvY3VtZW50YXRpb24pLiBUaGUgcGFja2FnZSBuZWVkcyB0byBiZSBpbnN0YWxsZWQgdG8gdXNlIHRoaXMgZmVhdHVyZS4NCiAgICAgICAgY29kZV9mb2xkaW5nOiAgICAiaGlkZSIgICAgICMgbm9uZSBzaG93IGhpZGUNCiAgICAgICAgY29kZV9kb3dubG9hZDogICB5ZXMgICAgICAgICMgeWVzIG5vDQogICAgICAgIGZpZ19jYXB0aW9uOiB5ZXMgICAgICAgICMgeWVzIG5vDQogICAgICAgIGZpZ193aWR0aCA6IDE0DQogICAgICAgIGZpZ19oZWlnaHQgOiAxMA0KICAgICAgICBmaWdfcmV0aW5hIDogMg0KICAgICAgICB0aGVtZTogICAgICAgZGVmYXVsdCAgICAgICAgIyBjZXJ1bGVhbiBqb3VybmFsIGZsYXRseSByZWFkYWJsZSBwYXBlciBzYW5kc3RvbmUgLi4uDQogICAgICAgIGRmX3ByaW50OiAgICBkZWZhdWx0ICAgICAgICAjIHBhZ2VkIGthYmxlIHRpYmJsZSBkZWZhdWx0DQogICAgICAgIG51bWJlcl9zZWN0aW9uczogeWVzICAgICAgICAjIEF1dG9tYXRpYyBudW1iZXJpbmcgb2Ygc2VjdGlvbnM6IHllcyBubw0KICAgICAgICBhbmNob3Jfc2VjdGlvbnMgOiBGQUxTRQ0KICAgICAgICBzZWN0aW9uX2RpdnMgOiBUUlVFICAgICAjIFdyYXAgc2VjdGlvbnMgaW4gPGRpdj4gdGFncywgYW5kIGF0dGFjaCBpZGVudGlmaWVycyB0byB0aGUgZW5jbG9zaW5nIDxkaXY+IA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHJhdGhlciB0aGFuIHRoZSBoZWFkZXIgaXRzZWxmLg0KICAgICAgICBkZXYgOiAic3ZnIiAgICAgICAgICAgICAgICAjIEdyYXBoaWNzIGRldmljZSB0byB1c2UgZm9yIGZpZ3VyZSBvdXRwdXQgKGRlZmF1bHRzIHRvIHBuZykNCiAgICAgICAgc2VsZl9jb250YWluZWQgOiBUUlVFDQogICAgICAgIGV4dHJhX2RlcGVuZGVuY2llcyA6IE5VTEwgICAgIyBFeHRyYSBkZXBlbmRlbmNpZXMgYXMgYSBsaXN0IG9mIHRoZSBodG1sX2RlcGVuZGVuY3kgY2xhc3Mgb2JqZWN0cyB0eXBpY2FsbHkgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBnZW5lcmF0ZWQgYnkgaHRtbHRvb2xzOmh0bWxEZXBlbmRlbmN5KCkuDQogICAgICAgIGNzcyA6IHN0eWxlLmNzcyAgICAgIyBDU1MgYW5kL29yIFNhc3MgZmlsZXMgdG8gaW5jbHVkZS4gRmlsZXMgd2l0aCBhbiBleHRlbnNpb24gb2YgLnNhc3Mgb3IgLnNjc3MgYXJlIGNvbXBpbGVkIHRvIA0KICAgICAgICAgICAgICAgICAgICAgICAjIENTUyB2aWEgc2Fzczo6c2FzcygpLiBBbHNvLCBpZiB0aGVtZSBpcyBhIGJzbGliOjpic190aGVtZSgpIG9iamVjdCwgU2FzcyBjb2RlIG1heSByZWZlcmVuY2UgDQogICAgICAgICAgICAgICAgICAgICAgICMgdGhlIHJlbGV2YW50IEJvb3RzdHJhcCBTYXNzIHZhcmlhYmxlcywgZnVuY3Rpb25zLCBtaXhpbnMsIGV0Yy4NCiAgICAgICAgaW5jbHVkZXMgOiBOVUxMICAgICAgICAjIE5hbWVkIGxpc3Qgb2YgYWRkaXRpb25hbCBjb250ZW50IHRvIGluY2x1ZGUgd2l0aGluIHRoZSBkb2N1bWVudCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyAodHlwaWNhbGx5IGNyZWF0ZWQgdXNpbmcgdGhlIGluY2x1ZGVzIGZ1bmN0aW9uKQ0KICAgICAgICBrZWVwX21kIDogRkFMU0UgICAgICAgICMgS2VlcCB0aGUgbWFya2Rvd24gZmlsZSBnZW5lcmF0ZWQgYnkga25pdHRpbmcuDQogICAgICAgIGxpYl9kaXIgOiBOVUxMICAgICAgICAgICAgICMgICAgRGlyZWN0b3J5IHRvIGNvcHkgZGVwZW5kZW50IEhUTUwgbGlicmFyaWVzIChlLmcuIGpxdWVyeSwgYm9vdHN0cmFwLCBldGMuKSANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBpbnRvLiBCeSBkZWZhdWx0IHRoaXMgd2lsbCBiZSB0aGUgbmFtZSBvZiB0aGUgZG9jdW1lbnQgd2l0aCBfZmlsZXMgYXBwZW5kZWQgdG8gaXQuDQogICAgICAgIG1kX2V4dGVuc2lvbnMgOiBOVUxMICAgICAgICMgTWFya2Rvd24gZXh0ZW5zaW9ucyB0byBiZSBhZGRlZCBvciByZW1vdmVkIGZyb20gdGhlIGRlZmF1bHQgZGVmaW5pdGlvbiBvZiANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgUiBNYXJrZG93bi4gU2VlIHRoZSBybWFya2Rvd25fZm9ybWF0IGZvciBhZGRpdGlvbmFsIGRldGFpbHMuDQogICAgICAgIHBhbmRvY19hcmdzIDogTlVMTCAgICAgICMgQWRkaXRpb25hbCBjb21tYW5kIGxpbmUgb3B0aW9ucyB0byBwYXNzIHRvIHBhbmRvYw0KICAgICAgICB0ZW1wbGF0ZSA6ICJkZWZhdWx0IiAgICAgICAjIFBhbmRvYyB0ZW1wbGF0ZSB0byB1c2UgZm9yIHJlbmRlcmluZy4gUGFzcyAiZGVmYXVsdCIgdG8gdXNlIHRoZSBybWFya2Rvd24gDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHBhY2thZ2UgZGVmYXVsdCB0ZW1wbGF0ZTsgcGFzcyBOVUxMIHRvIHVzZSBwYW5kb2MncyBidWlsdC1pbiB0ZW1wbGF0ZTsgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHBhc3MgYSBwYXRoIHRvIHVzZSBhIGN1c3RvbSB0ZW1wbGF0ZSB0aGF0IHlvdSd2ZSBjcmVhdGVkLiANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgTm90ZSB0aGF0IGlmIHlvdSBkb24ndCB1c2UgdGhlICJkZWZhdWx0IiB0ZW1wbGF0ZSB0aGVuIHNvbWUgZmVhdHVyZXMgb2YgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGh0bWxfZG9jdW1lbnQgd29uJ3QgYmUgYXZhaWxhYmxlIChzZWUgdGhlIFRlbXBsYXRlcyBzZWN0aW9uIGJlbG93IGZvciBtb3JlIGRldGFpbHMpLg0KICAgICAgICBtYXRoX21ldGhvZCA6ICJkZWZhdWx0IiAgICAgIyBNYXRoIHJlbmRlcmluZyBlbmdpbmUgdG8gdXNlLiBUaGlzIHdpbGwgZGVmaW5lIHRoZSBtYXRoIG1ldGhvZCB0byB1c2Ugd2l0aCBQYW5kb2MuDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIEl0IGNhbiBiZSBhIHN0cmluZyBmb3IgdGhlIGVuZ2luZSwgb25lIG9mICJtYXRoamF4IiwgIm1hdGhtbCIsICJ3ZWJ0ZXgiLCAia2F0ZXgiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyAiZ2xhZHRleCIsIG9yICJyLWthdGV4IiBvciAiZGVmYXVsdCIgZm9yIG1hdGhqYXguDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgSXQgY2FuIGJlIGEgbGlzdCBvZg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIC0gZW5naW5lOiBvbmUgb2YgIm1hdGhqYXgiLCAibWF0aG1sIiwgIndlYnRleCIsICJrYXRleCIsIG9yICJnbGFkdGV4Ii4gDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgLSB1cmw6IEEgc3BlY2lmaWMgdXJsIHRvIHVzZSB3aXRoIG1hdGhqYXgsIGthdGV4IG9yIHdlYnRleC4gDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBOb3RlIHRoYXQgZm9yIGVuZ2luZSA9ICJtYXRoamF4IiwgdXJsID0gImxvY2FsIiB3aWxsIHVzZSBhIGxvY2FsIHZlcnNpb24gb2YgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBNYXRoSmF4ICh3aGljaCBpcyBjb3BpZWQgaW50byB0aGUgb3V0cHV0IGRpcmVjdG9yeSkuDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBGb3IgZXhhbXBsZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIG91dHB1dDoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAjICAgIGh0bWxfZG9jdW1lbnQ6DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIyAgICAgICAgbWF0aF9tZXRob2Q6DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIyAgICAgICAgZW5naW5lOiBrYXRleA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgICAgICAgIHVybDogaHR0cHM6Ly9jZG4uanNkZWxpdnIubmV0L25wbS9rYXRleEAwLjExLjEvZGlzdA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgICAgICAgIFNlZSBQYW5kb2MncyBNYW51YWwgYWJvdXQgTWF0aCBpbiBIVE1MIGZvciB0aGUgZGV0YWlscyBhYm91dCBQYW5kb2MgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIyAgICAgICAgc3VwcG9ydGVkIG1ldGhvZHMuDQoNCiAgICAgICAgICAgICAgICAgICAgICAgICMgVXNpbmcgbWF0aF9tZXRob2QgPSAici1rYXRleCIgd2lsbCBvcHQtaW4gc2VydmVyIHNpZGUgcmVuZGVyaW5nIHVzaW5nIEthVGVYIHRoYW5rcyB0byANCiAgICAgICAgICAgICAgICAgICAgICAgICMga2F0ZXggUiBwYWNrYWdlLiANCiAgICAgICAgICAgICAgICAgICAgICAgICMgVGhpcyBpcyB1c2VmdWwgY29tcGFyZWQgdG8gbWF0aF9tZXRob2QgPSAia2F0ZXgiIHRvIGhhdmUgbm8gSlMgZGVwZW5kZW5jeSwgDQogICAgICAgICAgICAgICAgICAgICAgICAjIG9ubHkgYSBDU1MgZGVwZW5kZW5jeSBmb3Igc3R5bGluZyBlcXVhdGlvbi4NCiAgICAgICAgbWF0aGpheCA6ICJkZWZhdWx0IiAgICAgICAgIyBJbmNsdWRlIG1hdGhqYXguIFRoZSAiZGVmYXVsdCIgb3B0aW9uIHVzZXMgYW4gaHR0cHMgVVJMIGZyb20gYSBNYXRoSmF4IENETi4gDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIFRoZSAibG9jYWwiIG9wdGlvbiB1c2VzIGEgbG9jYWwgdmVyc2lvbiBvZiBNYXRoSmF4ICh3aGljaCBpcyBjb3BpZWQgaW50byANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgdGhlIG91dHB1dCBkaXJlY3RvcnkpLiBZb3UgY2FuIHBhc3MgYW4gYWx0ZXJuYXRlIFVSTCBvciBwYXNzIE5VTEwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHRvIGV4Y2x1ZGUgTWF0aEpheCBlbnRpcmVseS4NCi0tLQ0KDQoNCmBgYHtyIGNodW5rIG9wdGlvbnMsIGVjaG89Rn0NCiMgQ2h1bmsgb3B0aW9ucw0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KA0KICBlY2hvICAgICAgID0gVCwgICAgIyBTaG91bGQgYmxvY2tzIHdpdGggcHJvZ3JhbSBjb2RlIGJlIHNob3duIGluIGtuaXR0ZWQgZG9jdW1lbnRzPw0KICBldmFsICAgICAgID0gVFJVRSwgICAgIyBTaG91bGQgcHJvZ3JhbSBjb2RlIGJlIGV2YWx1YXRlZD8NCiAgZmlnLmhlaWdodCA9IDYsICAgICAgICMgRGVmYXVsdCBoZWlnaHQgZm9yIHBsb3RzLg0KICBmaWcud2lkdGggID0gMTAsICAgICAgICMgRGVmYXVsdCB3aWR0aCBmb3IgcGxvdHMuDQogIGZpZy5hbGlnbiAgPSAiY2VudGVyIiwgIyBEZWZhdWx0IGFsaWdubWVudCBmb3IgcGxvdHMgaW4ga25pdHRlZCBkb2N1bWVudHMuDQogIHdhcm5pbmcgPSBGDQopDQoNCmBgYA0KDQpgYGB7ciBsaWJyYXJpZXMgYW5kIGRhdGEgbG9hZGluZywgaW5jbHVkZSA9IEZ9DQoNCiMgTElCUkFSSUVTIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCmxpYnJhcnkoY29uZmxpY3RlZCkgICAgIyBHZXQgYSB3YXJuaW5nL2Vycm9yIGlmIHNldmVyYWwgZnVuY3Rpb25zIHdpdGggdGhlIHNhbWUgbmFtZSBleGlzdC4NCmxpYnJhcnkobWFncml0dHIpICAgICAgIyBPcGVyYXRvciAlPiUgYW5kIGFkZGl0aW9uYWwgcGlwZS1mcmllbmRseSBmdW5jdGlvbnMuDQpsaWJyYXJ5KHRpZHl2ZXJzZSkgICAgICMgVGhlIG1haW4gInRpZHl2ZXJzZSIgcGFja2FnZXMuDQpsaWJyYXJ5KG9wZW54bHN4KSAgICAgICMgV3JpdGUgZGF0YSB0byBFeGNlbCBmaWxlcy4NCmxpYnJhcnkoc3RyaW5ncikNCmxpYnJhcnkoa25pdHIpDQpsaWJyYXJ5KGthYmxlRXh0cmEpDQpsaWJyYXJ5KHBhbmRlcikNCmxpYnJhcnkoRFQpDQpsaWJyYXJ5KGphbml0b3IpDQoNCmNvbmZsaWN0ZWQ6OmNvbmZsaWN0c19wcmVmZXIoZHBseXI6OmZpbHRlcikNCg0KIyBEQVRBIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KcG9zdCA9IHJlYWQueGxzeCgiQ29waWUgZGUgcmVzdWx0YXRzIFEyIGNvcGllLnhsc3giLCBzaGVldCA9IDEpDQpwcmUgPSByZWFkLnhsc3goIkNvcGllIGRlIHJlc3VsdGF0cyBRMSBjb3BpZS54bHN4Iiwgc2hlZXQgPSAxKQ0KYGBgDQoNCmBgYHtyIGRhdGEgbWFuYWdlbWVudCwgaW5jbHVkZSA9IEZ9DQojIENvbG5hbWVzKCkgdG8gbG93ZXJjYXNlDQpjb2xuYW1lcyhwcmUpID0gdG9sb3dlcihjb2xuYW1lcyhwcmUpKQ0KY29sbmFtZXMocG9zdCkgPSB0b2xvd2VyKGNvbG5hbWVzKHBvc3QpKQ0KDQojIE1FUkdJTkcgUFJFIEUgUE9TVCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQpwcmUgPSBwcmUgJT4lIA0KICAgIHNlbGVjdCgtY29udGFpbnMoYygiaWQiLCJzdWJtaXRkYXRlIiwibGFzdHBhZ2UiLCJzdGFydGxhbmd1YWdlIikpKSAlPiUgDQogICAgcmVuYW1lKCJmaWxpZXJlIj1iMSwgImlkIiA9IGExKSAlPiUgDQogICAgbXV0YXRlKHRlc3QgPSAicHJlIikNCg0KcG9zdCA9IHBvc3QgJT4lDQogICAgZmlsdGVyKCFpcy5uYShzdWJtaXRkYXRlKSkgJT4lIA0KICAgIHNlbGVjdCgtY29udGFpbnMoYygiaWQiLCJzdWJtaXRkYXRlIiwibGFzdHBhZ2UiLCJzdGFydGxhbmd1YWdlIiwieDI2IiwieDI3IikpKSAlPiUgDQogICAgcmVuYW1lKCJpZCIgPSBhMSkgJT4lIA0KICAgIGxlZnRfam9pbihwcmVbLGMoImlkIiwiZmlsaWVyZSIpXSwgYnkgPSAiaWQiKSAlPiUgDQogICAgcmVsb2NhdGUoZmlsaWVyZSwgLmFmdGVyID0gImlkIikgJT4lIA0KICAgIG11dGF0ZSh0ZXN0ID0gInBvc3QiKQ0KDQojIE1lcmdpbmcNCmRhdGEgPSByYmluZChwcmUscG9zdCkgJT4lIHRpYmJsZQ0KDQojIERBVEEgTUFOQUdFTUVOVCBtZXJnZWQgREYgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KZGF0YSA9IGRhdGEgJT4lIA0KICAgIG11dGF0ZShhY3Jvc3MoczFxMTpzN3EyLCBhcy5udW1lcmljKSkgJT4lIA0KICAgIGRpc3RpbmN0KCkgJT4lIA0KICAgIHJlbG9jYXRlKHRlc3QsIC5hZnRlciA9ICJpZCIpICU+JQ0KICAgIG11dGF0ZShmaWxpZXJlID0gY2FzZV93aGVuKGZpbGllcmUgPT0gIsOpdHVkaWFudChlKSBlbiBtYcOvZXV0aXF1ZSIgfiAibWFpZXV0aXF1ZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsaWVyZSA9PSAiw6l0dWRpYW50KGUpIGVuIG9ydGhvcGhvbmllIiB+ICJvcnRob3Bob25pZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsaWVyZSA9PSAiw6l0dWRpYW50KGUpIGVuIHBoYXJtYWNpZSIgfiAicGhhcm1hY2llIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxpZXJlID09ICLDqXR1ZGlhbnQoZSkgSURFIiB+ICJJREUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGllcmUgPT0gIsOpdHVkaWFudChlKSBNS0UiIH4gIk1LRSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsaWVyZSA9PSAiaW50ZXJuZSBkZSBtw6lkZWNpbmUgZ8OpbsOpcmFsZSIgfiAibWVkZWNpbmUgZ2VuZXJhbGUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiBOQV9jaGFyYWN0ZXJfDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQ0KICAgICAgICAgICApDQoNCiMgQWRkaW5nIG1lYW4gc2NvcmUgY29sdW1uDQpkYXRhID0gZGF0YSAlPiUgbXV0YXRlKHNjb3JlID0gcm93TWVhbnMoYWNyb3NzKHMxcTE6czdxMiksbmEucm09VCkpDQpgYGANCg0KDQojIEV4cGxvcmF0b3J5IGFuYWx5c2lzDQojIyBTZWxlY3Rpb24gZGVzIHF1ZXN0aW9ubmFpcmVzDQpgYGB7ciBmaWx0ZXJpbmcgb3V0IGludmlkYWxpZCBxdWVzdGlvbm5haXJlcywgaW5jbHVkZSA9IEZ9DQpyb3dzXzEgPSBucm93KGRhdGEpDQp1bmlxdWVfaWRzXzEgPSBuX2Rpc3RpbmN0KGRhdGEkaWQpDQoNCiMgUmVtb3ZpbmcgbWlzc2luZyBJRHMgcm93cyAobj00KQ0KZGF0YSA9IGRhdGEgJT4lIGZpbHRlcighaXMubmEoaWQpKQ0KdW5pcXVlX2lkc18yID0gbl9kaXN0aW5jdChkYXRhJGlkKQ0Kcm93c18yID0gbnJvdyhkYXRhKQ0KDQojIENvbXB1dGluZyBtaXNzaW5nIHZhbHVlcyBwZXIgcm93DQpkYXRhID0gZGF0YSAlPiUgZmlsdGVyKCFpcy5uYShpZCkpICU+JSANCiAgICBtdXRhdGUobmFfY291bnRzID0gcm93U3VtcyhhY3Jvc3MoczFxMTpzN3EyLCBpcy5uYSkpKQ0KDQojIEVtcHR5IHF1ZXN0aW9ubmFpcmVzDQplbXB0eV9xID0gc3VtKGRhdGEkbmFfY291bnRzPT0yMCkNCg0KDQojIFJlbW92aW5nIHRvdGFsbHkgaW5jb21wbGV0ZSBxdWVzdGlvbm5haXJlcw0KZGF0YSA9IGRhdGEgJT4lIGZpbHRlcihuYV9jb3VudHM8MjApDQp1bmlxdWVfaWRzXzMgPSBuX2Rpc3RpbmN0KGRhdGEkaWQpDQpyb3dzXzMgPSBucm93KGRhdGEpDQoNCmBgYA0KDQpBdSB0b3V0IGTDqWJ1dCBvbiBhICoqYHIgcm93c18xYCoqIGxpZ25lcyBldCAqKmByIHVuaXF1ZV9pZHNfMWAqKiBJRHMuICANCiAgPGJyPg0KQXByw6hzIGF2b2lyIGV4Y2x1IDQgbGlnbmVzIMOgIGNhdXNlIGRlIG1pc3NpbmcgSUQsIG9uIGRlc2NlbmQgw6AgKipgciAocm93c18xIC0gNClgKiogcXVlc3Rpb25uYWlyZXMgZXQgKipgciB1bmlxdWVfaWRzXzJgKiogSURzIChsJ0lEICJ2YWxldXIgbWFucXVhbnRlIiBuJ2VzdCBwbHVzIGNvbXB0YWJpbGlzw6ksIGMnZXN0IHBvdXIgw6dhIHF1J29uICJwZXJkIiB1biBJRCkuICANCiAgPGJyPg0KU2FjaGFudCBxdWUgKipgciB1bmlxdWVfaWRzXzJgKip4Mj0qKmByICh1bmlxdWVfaWRzXzIqMilgKipvbiBhICoqYHIgcm93c18yIC0gNzYwYCoqIGVudHLDqWVzIGRlIHRyb3AuDQogIDxicj4NCk9uIHJldHJvdXZlICoqYHIgZW1wdHlfcWAqKiBxdWVzdGlvbm5haXJlcyBjb21wbGV0ZW1lbnQgdmlkZXMsIHF1J29uIHBldXQgZXhjbHVyZSBjZSBxdWkgbm91cyBkb25uZSAqKmByIHJvd3NfM2AqKiBxdWVzdGlvbm5haXJlcyBldCAqKmByIHVuaXF1ZV9pZHNfM2AqKiBJRHMgdW5pcXVlcy4gIA0KICA8YnI+DQpPbiBlc3QgdGpycyB0csOocyBsb2luIGRlIG5vdHJlIG9iamVjdGlmIGRlIGVudmlyb24gKipgciAodW5pcXVlX2lkc18yKjIpYCoqIHF1ZXN0aW9ubmFpcmVzICgqKmByICh1bmlxdWVfaWRzXzMqMilgKiogbWFpbnRlbmFudCBxdSdvbiBhICoqYHIgdW5pcXVlX2lkc18zYCoqIElEcykuDQogIDxicj4NCg0KRG9uYywgb24gYSBmb3JjZW1lbnQgZGVzIElEcyBwb3VyIGxlc3F1ZWxzIG9uIGEgKio+MioqIGVudHLDqWVzLiBWb3lvbnMgZGUgbGVzIG1ldHRyZSBlbiBldmlkZW5jZS4NCg0KYGBge3IgSURzIHdpdGggdG9vIG1hbnkgZW50cmllc30NCmRhdGEgJT4lIA0KICAgIGdyb3VwX2J5KGlkKSAlPiUgDQogICAgc3VtbWFyaXNlKG49bigpKSAlPiUNCiAgICBhcnJhbmdlKGRlc2MobikpICU+JQ0KICAgIGRhdGF0YWJsZShvcHRpb25zID0gbGlzdChwYWdlTGVuZ3RoID0gMTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICNkb20gPSAndCcsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjcm9sbFggPSBUUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aCA9ICJhdXRvIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2Nyb2xsWCA9IFQNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSkNCg0KcHJvYmxlbWF0aWNfSURzID0gZGF0YSAlPiUgZ3JvdXBfYnkoaWQpICU+JSBzdW1tYXJpc2Uobj1uKCkpICU+JSBmaWx0ZXIobj4yKSAlPiUgbnJvdw0KDQpgYGANCiAgDQogIDxicj4NCkNvbW1lIHR1IHBldXggbGUgdm9pciBvbiBzZW1ibGUgYXZvaXIgYHIgcHJvYmxlbWF0aWNfSURzYCBJRHMgcHJlc2VudHMgKiphdSBtb2lucyoqIDMgZm9pcy4NCiAgPGJyPg0KQ3JldXNvbnMgcGx1cyBsb2luIHBvdXIgdm9pciBzaSBvbiBpZGVudGlmaWUgdW4gZ3JvdXBlIGQnSURzIHByb2JsZW1hdGlxdWUuIFRow6lvcmlxdWVtZW50LCBzaSBsZXMgZ2VucyBhdmFpZW50IHJlc3BlY3TDqSBsZXMgcsOpZ2xlcyBwb3VyIGxhIGNyw6lhdGlvbiBkZSBsJ2lkZW50aWZpYW50IGFub255bWUsIGwnaWRlbnRpZmlhbnQgZGV2cmFpdCBzdWl2cmUgbGUgKnBhdHRlcm4qIHN1aXZhbnQ6IDEgY2hpZmZyZSAtIDIgbGV0dHJlcyAtIDIgY2hpZmZyZXMuICANCg0KVm95b25zIHBvdXIgY29tYmllbiBkZSBsaWduZXMgY2UgKnBhdHRlcm4qIGVzdCByZXNwZWN0w6k6DQpgYGB7ciBsb29raW5nIGZvciBJRHMgbm90IGZvbGxvd2luZyB0aGUgcnVsZXN9DQpzdHJfZGV0ZWN0KGRhdGEkaWQsICJbOmRpZ2l0Ol17MX1bOmFscGhhOl17Mn1bOmRpZ2l0Ol17Mn0iKSAlPiUgDQogICAgdGFibGUgJT4lDQogICAgcGFuZGVyDQpgYGANCg0KQ2VsYSBub3VzIGRpdCBxdWUgKiptw6ptZSBzaSoqIG9uIHJlZ2FyZGUgc2V1bGVtZW50IGxlcyBnZW5zIHF1aSBvbnQgcmVzcGVjdMOpIGxhIHByb2NlZHVyZSBwb3VyIGxhIGNyw6lhdGlvbiBkZXMgSURzLCBvbiDDoCB0anJzIGRlcyBsaWduZXMgZGUgdHJvcC4gRCdhYm9yZCwgcmVnYXJkb25zIGxlcyBlbnRyw6lzIGRlcyBnZW5zIHF1aSBvbnQgdGFww6kgdW4gSUQgYXUgcGlmLg0KDQpgYGB7ciBkYXRhZnJhbWUgSURzIGFiZXJyYW50c30NCmRhdGEgJT4lIA0KICAgIGZpbHRlcighc3RyX2RldGVjdChpZCwgIls6ZGlnaXQ6XXsxfVs6YWxwaGE6XXsyfVs6ZGlnaXQ6XXsyfSIpKSAlPiUNCiAgICBhcnJhbmdlKGlkKSAlPiUgDQogICAgZGF0YXRhYmxlKG9wdGlvbnMgPSBsaXN0KHBhZ2VMZW5ndGggPSAxMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI2RvbSA9ICd0JywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2Nyb2xsWCA9IFRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoID0gImF1dG8iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY3JvbGxYID0gVA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICApKQ0KYGBgDQogIA0KICA8YnI+DQpOw6lhbm1vaW5zLCBzJ2lscyBvbnQgdXRpbGlzw6kgMiBmb2lzICoqbGUgbcOqbWUqKiBpZGVudGlmaWFudCAqYWJlcnJhbnQqIG9uIHBvdXJyYSBxdWFuZCBtw6ptZSBsZXMgYXBwYXJpZXIuIFZveW9ucyBkb25jIGxlcyBJRHMgcXVpIGFwcGFyYWlzc2VudCAqKj4yKiogZm9pcy4gTGVzIElEcyAgKmFiZXJyYW50cyogcXVpIGFwcGFyYWlzc2VudCAqKjIqKiBmb2lzIG9uIHBldXQgbGVzIHV0aWxpc2VyLCBsZXMgSURzIHF1aSBhcHBhcmFpc3NlbnQgcXUndW5lIHNldWxlIGZvaXMsIGlkZW0sIG9uIHBldXQgbGVzIGdhcmRlciBwb3VyIGxhIHBhcnRpZSBkZXNjcmlwdGl2ZSAoY2FycmVtZW50IGlscyBuZSBzZXJhIHBhcyBwb3NzaWJsZSBkZSBsZXMgdXRpbGlzZXIgcG91ciBsYSBjb21wYXJhaXNvbiBhdmFudC1hcHLDqHMpLg0KICA8YnI+DQogIA0KYGBge3IgSURzIGFiZXJyYW50cyBwcmVzZW50ZXMgMisgZm9pc30NCmRhdGEgJT4lIA0KICAgIGZpbHRlcighc3RyX2RldGVjdChpZCwgIls6ZGlnaXQ6XXsxfVs6YWxwaGE6XXsyfVs6ZGlnaXQ6XXsyfSIpKSAlPiUNCiAgICBncm91cF9ieShpZCkgJT4lDQogICAgc3VtbWFyaXNlKG49bigpKSAlPiUgDQogICAgYXJyYW5nZShkZXNjKG4pKSAlPiUNCiAgICBkYXRhdGFibGUob3B0aW9ucyA9IGxpc3QocGFnZUxlbmd0aCA9IDEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjZG9tID0gJ3QnLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY3JvbGxYID0gVFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGggPSAiYXV0byIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjcm9sbFggPSBUDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICkpDQpgYGANCiAgDQpPbiB2b2l0IHF1ZSBsZSBzZXVsIElEIHByb2JsZW1hdGlxdWUgcGFybWkgbGVzICphYmVycmFudHMqIGVzdCAqKiIxMjM0NSIqKi48YnI+DQpFc3QtY2UgcXVlIGxhIGZpbGnDqHJlIHBvdXJyYWl0IG5vdXMgYWlkZXI/IFZveW9ucy4NCg0KYGBge3IgZmlsdGVyaW5nIG9uIElEICIxMjM0NSJ9DQpkYXRhICU+JSANCiAgICBmaWx0ZXIoaWQ9PSIxMjM0NSIpICU+JQ0KICAgIGRhdGF0YWJsZShvcHRpb25zID0gbGlzdChwYWdlTGVuZ3RoID0gMTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICNkb20gPSAndCcsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjcm9sbFggPSBUUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aCA9ICJhdXRvIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2Nyb2xsWCA9IFQNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSkNCmBgYA0KICANCk9uIHNlbWJsZSBhdm9pciAxIElERSBldCAxIE1HLCBxdWkgb250IHVuIGRvdWJsb24gZGUgIjLDqG1lIHRlc3QiLiANClNpIG9uIHJlZ2FyZGUgYXZlYyBhdHRlbnRpb24gbGEgbGlnbmUgMyBldCA0IHNvbnQgaWRlbnRpcXVlcywgYXZlYyB1bmUgImZpbGnDqHJlIiBkaWZmw6lyZW50ZS4gPGJyPg0KU2kgbGEgbGlnbmUgMyBldCA0IMOpdGFpZW50IHBhciBleGVtcGxlICJJREUiIGV0IGxhIGxpZ25lIDUgZXQgNiDDqXRhaWVudCAibWVkZWNpbmUgZ2VuZXJhbGUiIG9uIGF1cmFpdCBpZGVudGlmacOpIGRlcyBkb3VibG9ucyAtLT4gcHJvYmzDqG1lIHLDqXNvbHUuIA0KTWFpcyBkYW5zIGNlIGNhcyBvbiBhIGRlcyBkb3VibG9ucyAqKkVUKiogMiBwZXJzb25uZXMgcXVpIG9udCByZW50csOpIDIgZm9pcyBsZSAiMsOobWUgdGVzdCIgZW4gY2hhbmdlYW50IGF1c3NpIGRlIGZpbGnDqHJlLiBPdSBJbCBlc3QgZG9uYyBpbXBvc3NpYmxlIGRlIHJhdHRhY2hlciBjZXMgcXVlc3Rpb25uYWlyZXMgw6AgdW4gInRlc3QgMSIuDQpDZSBxdWkgZXN0IHRyw6hzIHRyw6hzIGJpemFycmUsIGVzdCBxdWUgbGVzIGxpZ25lcyAzIGV0IDUgc29udCBJREVOVElRVUVTIGF1eCBsaWduZXMgNCBldCA2LiBDZSBxdSdvbiBwZXV0IGZhaXJlLCBlc3QgcHJlbmRyZSBsYSBtb3llbm5lIGRlcyBsaWduZXMgMy01IGV0IDQtNi4gTGUgbcOqbWUgYXBwcm9jaGUgbm91cyBzZXJhIHV0aWxlIHBvdXIgZ8OpcmVyIGxlcyBJRHMgKm5vbiBhYmVycmFudHMqIGRvdWJsb25zIHF1aSBzb250IGxlcyBzdWl2YW50czoNCg0KDQpgYGB7ciBJRHMgbm9uIGFiZXJyYW50cyBkZSB0cm9wfQ0KZGF0YSAlPiUgDQogICAgZmlsdGVyKHN0cl9kZXRlY3QoaWQsICJbOmRpZ2l0Ol17MX1bOmFscGhhOl17Mn1bOmRpZ2l0Ol17Mn0iKSkgJT4lDQogICAgZ3JvdXBfYnkoaWQpICU+JQ0KICAgIG11dGF0ZShuPW4oKSkgJT4lIA0KICAgZmlsdGVyKG4+MikgJT4lDQogICAgcmVsb2NhdGUobiwgLmFmdGVyID0gaWQpICU+JSANCiAgICBhcnJhbmdlKGRlc2MobikpICU+JSANCiAgICBkYXRhdGFibGUob3B0aW9ucyA9IGxpc3QocGFnZUxlbmd0aCA9IDEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjZG9tID0gJ3QnLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY3JvbGxYID0gVFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGggPSAiYXV0byIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjcm9sbFggPSBUDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICkpDQoNCg0KZGF0YSA9IGRhdGElPiUNCiAgICAgZ3JvdXBfYnkoaWQsIHRlc3QsIGZpbGllcmUpICU+JQ0KICAgICBzdW1tYXJpc2UoYWNyb3NzKHMxcTE6bGFzdF9jb2woKSwgfm1lYW4oLiwgbmEucm0gPSBUUlVFKSksIC5ncm91cHMgPSAiZHJvcCIpDQpgYGANCiAgDQoNClZ1IHF1ZSAiSUQiIG5lIHN1ZmZpdCBwb3VyIGlkZW50aWZpZXIgdW5pcXVlbWVudCBsZXMgbGlnbmVzLCBzaSBvbiBwcmVuZCAiSUQiICsgInRlc3QiICsgImZpbGllcmUiIGV0IG9uIGZhaXQgbGEgbW95ZW5uZSBkZXMgbGlnbmVzIGFtYmlndWVzIG9uIGRldnJhaXQgcydlbiBzb3J0aXIgcGFzIG1hbC4NCkNlbGEgbm91cyBsYWlzc2UgYXZlYyBgciBucm93KGRhdGEpYCBxdWVzdGlvbm5haXJlcy4gPGJyPg0KQm9uLCBvbiBzYWl0IGRlasOgIHF1J29uIGEgZGVzIElEcyBxdWkgYXBwYXJhaXNzZW50IHRyb3Agc291dmVudCBtYWlzIHNpIG9uIHByZW5kIElELWZpbGllcmUsIGVzdC1jZSBxdWUgbWFpbnRlbmFudCBvbiBhIG1heCAyIGxpZ25lcyBwYXIgY291cGxlIElELWZpbGllcmU/DQogIA0KDQpgYGB7ciB1bmlxdWVzIElELUZJTElFUkV9DQpkYXRhICU+JSANCiAgICBncm91cF9ieShpZCxmaWxpZXJlKSAlPiUNCiAgICBzdW1tYXJpc2Uobj1uKCkpICU+JSANCiAgICBhcnJhbmdlKGRlc2MobikpICU+JQ0KICAgIGRhdGF0YWJsZShvcHRpb25zID0gbGlzdChwYWdlTGVuZ3RoID0gMTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICNkb20gPSAndCcsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjcm9sbFggPSBUUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aCA9ICJhdXRvIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2Nyb2xsWCA9IFQNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSkNCg0KYGBgDQo8YnI+DQoNCk91aSEgTm91cyBhdm9ucyBtYWludGVuYW50IDQxMyBpZGVudGl0w6kgdW5pcXVlcyBkb25uw6llcyBwYXIgSUQrRklMSUVSRS4gVnUgcXUnb24gYSBiZXNvaW4gZGUgImZpbGnDqHJlIiBwb3VyIGlkZW50aWZpZXIgbGVzIGdlbnMsIG9uIHZhIGVzY2x1cmUgbGVzIGxpZ25lcyBvw7kgImZpbGnDqHJlIiBuJ2VzdCBwYXMgcmVuc2VpZ27DqS4NCg0KYGBge3J9DQpmaWxpZXJlX25hID0gZGF0YSAlPiUgZmlsdGVyKGlzLm5hKGZpbGllcmUpKSAlPiUgbnJvdygpDQoNCiMgUkVNT1ZJTkcgTUlTU0lORyAiZmlsaWVyZSIgcm93cw0KZGF0YSA9IGRhdGEgJT4lIGZpbHRlcighaXMubmEoZmlsaWVyZSkpDQoNCiMgSG93IG1hbnkgcXVlc3Rpb25uYWlyZXMgbGVmdD8NCnF1ZXN0aW9ubmFpcmVzID0gbnJvdyhkYXRhKQ0KIyBIb3cgbWFueSB1bmlxdWUgaWRlbnRpZnRpZXM/DQppZHMgPSBkYXRhICU+JSBkaXN0aW5jdChpZCxmaWxpZXJlKSAlPiUgbnJvdw0KDQpgYGANCg0KT24gZXhjbHUgZG9uYyBgciBmaWxpZXJlX25hYCBsaWduZXMgY2FyIHZhbGV1ciBtYW5xdWFudGUuIE9uIGVzdCBtYWludGVuYW50IMOgICoqYHIgcXVlc3Rpb25uYWlyZXNgKiogcXVlc3Rpb25uYWlyZXMgcG91ciAqKmByIGlkc2AqKiBpZGVudGl0w6lzLiBWb3lvbnMgY29tYmllbiBkZSBnZW5zIG9uIHBldXQgYXBwYXJpZXIuDQoNCjxicj4NCmBgYHtyIGhvdyBtYW55IHBhaXJlZCBxdWVzdGlvbm5haXJlc30NCmRhdGEgJT4lIA0KICAgIGdyb3VwX2J5KGlkLGZpbGllcmUpICU+JQ0KICAgIHN1bW1hcmlzZShuPW4oKSwgLmdyb3Vwcz0iZHJvcCIpICU+JSANCiAgICBhcnJhbmdlKGRlc2MobikpICUkJQ0KICAgIHRhYmxlKG4pICU+JQ0KICAgIHBhbmRlcihjYXB0aW9uID0gIk5iIHF1ZXN0aW9ubmFpcmVzIGFwcGFyacOpcyBldCBub24iKQ0KYGBgDQoNCjxicj4NCg0KYGBge3IgZWNobz1GQUxTRSwgZmlnLmNhcD1jYXB0aW9uLCBvdXQud2lkdGg9ODAwLCBvdXQuaGVpZ2h0PTgwMH0NCiMgQ2FwdGlvbi9EZXNjcmlwdGlvbi4NCmNhcHRpb24gPC0gIkZsb3djaGFydCBpbmNsdXNpb24gcXVlc3Rpb25uYWlyZXMiDQoNCiMgUGF0aCBvciBVUkwgdG8gdGhlIGZpZ3VyZS4NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJmbG93Y2hhcnQucG5nIikNCmBgYA0KPGJyPg0KIyMjIyMjIyMjDQo8ZGl2IGNsYXNzPSJteGdyYXBoIiBzdHlsZT0ibWF4LXdpZHRoOjEwMCU7Ym9yZGVyOjFweCBzb2xpZCB0cmFuc3BhcmVudDsiIGRhdGEtbXhncmFwaD0ieyZxdW90O2hpZ2hsaWdodCZxdW90OzomcXVvdDsjMDAwMGZmJnF1b3Q7LCZxdW90O25hdiZxdW90Ozp0cnVlLCZxdW90O3Jlc2l6ZSZxdW90Ozp0cnVlLCZxdW90O3Rvb2xiYXImcXVvdDs6JnF1b3Q7em9vbSBsYXllcnMgdGFncyBsaWdodGJveCZxdW90OywmcXVvdDtlZGl0JnF1b3Q7OiZxdW90O19ibGFuayZxdW90OywmcXVvdDt4bWwmcXVvdDs6JnF1b3Q7Jmx0O214ZmlsZSZndDsmbHQ7ZGlhZ3JhbSBpZD1cJnF1b3Q7cHgzaG9ETTRZbFAwcFA3Z1VGR3FcJnF1b3Q7IG5hbWU9XCZxdW90O1BhZ2UtMVwmcXVvdDsmZ3Q7Jmx0O214R3JhcGhNb2RlbCBkeD1cJnF1b3Q7NjgwXCZxdW90OyBkeT1cJnF1b3Q7NTY4XCZxdW90OyBncmlkPVwmcXVvdDsxXCZxdW90OyBncmlkU2l6ZT1cJnF1b3Q7MTBcJnF1b3Q7IGd1aWRlcz1cJnF1b3Q7MVwmcXVvdDsgdG9vbHRpcHM9XCZxdW90OzFcJnF1b3Q7IGNvbm5lY3Q9XCZxdW90OzFcJnF1b3Q7IGFycm93cz1cJnF1b3Q7MVwmcXVvdDsgZm9sZD1cJnF1b3Q7MVwmcXVvdDsgcGFnZT1cJnF1b3Q7MVwmcXVvdDsgcGFnZVNjYWxlPVwmcXVvdDsxXCZxdW90OyBwYWdlV2lkdGg9XCZxdW90Ozg1MFwmcXVvdDsgcGFnZUhlaWdodD1cJnF1b3Q7MTEwMFwmcXVvdDsgbWF0aD1cJnF1b3Q7MFwmcXVvdDsgc2hhZG93PVwmcXVvdDswXCZxdW90OyZndDsmbHQ7cm9vdCZndDsmbHQ7bXhDZWxsIGlkPVwmcXVvdDswXCZxdW90Oy8mZ3Q7Jmx0O214Q2VsbCBpZD1cJnF1b3Q7MVwmcXVvdDsgcGFyZW50PVwmcXVvdDswXCZxdW90Oy8mZ3Q7Jmx0O214Q2VsbCBpZD1cJnF1b3Q7NFwmcXVvdDsgdmFsdWU9XCZxdW90O3JlbW92aW5nIG1pc3NpbmcgSURzIChuPTQpXCZxdW90OyBzdHlsZT1cJnF1b3Q7ZWRnZVN0eWxlPW5vbmU7aHRtbD0xO1wmcXVvdDsgcGFyZW50PVwmcXVvdDsxXCZxdW90OyBzb3VyY2U9XCZxdW90OzJcJnF1b3Q7IHRhcmdldD1cJnF1b3Q7M1wmcXVvdDsgZWRnZT1cJnF1b3Q7MVwmcXVvdDsmZ3Q7Jmx0O214R2VvbWV0cnkgcmVsYXRpdmU9XCZxdW90OzFcJnF1b3Q7IGFzPVwmcXVvdDtnZW9tZXRyeVwmcXVvdDsvJmd0OyZsdDsvbXhDZWxsJmd0OyZsdDtteENlbGwgaWQ9XCZxdW90OzJcJnF1b3Q7IHZhbHVlPVwmcXVvdDs4NzAgcXVlc3Rpb25uYWlyZXMgcmVudHLDqXNcJnF1b3Q7IHN0eWxlPVwmcXVvdDtyb3VuZGVkPTE7d2hpdGVTcGFjZT13cmFwO2h0bWw9MTtcJnF1b3Q7IHBhcmVudD1cJnF1b3Q7MVwmcXVvdDsgdmVydGV4PVwmcXVvdDsxXCZxdW90OyZndDsmbHQ7bXhHZW9tZXRyeSB4PVwmcXVvdDszNjVcJnF1b3Q7IHk9XCZxdW90OzQwXCZxdW90OyB3aWR0aD1cJnF1b3Q7MTIwXCZxdW90OyBoZWlnaHQ9XCZxdW90OzYwXCZxdW90OyBhcz1cJnF1b3Q7Z2VvbWV0cnlcJnF1b3Q7LyZndDsmbHQ7L214Q2VsbCZndDsmbHQ7bXhDZWxsIGlkPVwmcXVvdDs2XCZxdW90OyB2YWx1ZT1cJnF1b3Q7ZXhjbHVzaW9uIHF1ZXN0aW9ubmFpcmVzIHZpZGVzIChuPTE2KVwmcXVvdDsgc3R5bGU9XCZxdW90O2VkZ2VTdHlsZT1ub25lO2h0bWw9MTtcJnF1b3Q7IHBhcmVudD1cJnF1b3Q7MVwmcXVvdDsgc291cmNlPVwmcXVvdDszXCZxdW90OyB0YXJnZXQ9XCZxdW90OzVcJnF1b3Q7IGVkZ2U9XCZxdW90OzFcJnF1b3Q7Jmd0OyZsdDtteEdlb21ldHJ5IHJlbGF0aXZlPVwmcXVvdDsxXCZxdW90OyBhcz1cJnF1b3Q7Z2VvbWV0cnlcJnF1b3Q7LyZndDsmbHQ7L214Q2VsbCZndDsmbHQ7bXhDZWxsIGlkPVwmcXVvdDszXCZxdW90OyB2YWx1ZT1cJnF1b3Q7ODY2IHF1ZXN0aW9ubmFpcmVzJmFtcDtsdDticiZhbXA7Z3Q7MzgwIElEc1wmcXVvdDsgc3R5bGU9XCZxdW90O3doaXRlU3BhY2U9d3JhcDtodG1sPTE7cm91bmRlZD0xO1wmcXVvdDsgcGFyZW50PVwmcXVvdDsxXCZxdW90OyB2ZXJ0ZXg9XCZxdW90OzFcJnF1b3Q7Jmd0OyZsdDtteEdlb21ldHJ5IHg9XCZxdW90OzM2NVwmcXVvdDsgeT1cJnF1b3Q7MTgwXCZxdW90OyB3aWR0aD1cJnF1b3Q7MTIwXCZxdW90OyBoZWlnaHQ9XCZxdW90OzYwXCZxdW90OyBhcz1cJnF1b3Q7Z2VvbWV0cnlcJnF1b3Q7LyZndDsmbHQ7L214Q2VsbCZndDsmbHQ7bXhDZWxsIGlkPVwmcXVvdDs4XCZxdW90OyB2YWx1ZT1cJnF1b3Q7TGVzIElEcyBuZSBzb250IHBhcyBzdWZmaXNhbnRzIGRvbmMgamUgcmVncm91cGUgcG91ciBJRCArIEZJTElFUkUuJmFtcDtsdDticiZhbXA7Z3Q7U2kgcG91ciB1bmUgdHJpcGxldHRlIElEICsgRklMSUVSRSBqJiMzOTthaSB0anJzIHBsdXMgcXVlIDIgbGlnbmVzLCBqZSBwcmVuZHMgbGEgbW95ZW5uZVwmcXVvdDsgc3R5bGU9XCZxdW90O2VkZ2VTdHlsZT1ub25lO2h0bWw9MTtcJnF1b3Q7IHBhcmVudD1cJnF1b3Q7MVwmcXVvdDsgc291cmNlPVwmcXVvdDs1XCZxdW90OyB0YXJnZXQ9XCZxdW90OzdcJnF1b3Q7IGVkZ2U9XCZxdW90OzFcJnF1b3Q7Jmd0OyZsdDtteEdlb21ldHJ5IHJlbGF0aXZlPVwmcXVvdDsxXCZxdW90OyBhcz1cJnF1b3Q7Z2VvbWV0cnlcJnF1b3Q7LyZndDsmbHQ7L214Q2VsbCZndDsmbHQ7bXhDZWxsIGlkPVwmcXVvdDs1XCZxdW90OyB2YWx1ZT1cJnF1b3Q7ODUwIHF1ZXN0aW9ubmFpcmVzJmFtcDtsdDticiZhbXA7Z3Q7Mzc5IElEc1wmcXVvdDsgc3R5bGU9XCZxdW90O3doaXRlU3BhY2U9d3JhcDtodG1sPTE7cm91bmRlZD0xO1wmcXVvdDsgcGFyZW50PVwmcXVvdDsxXCZxdW90OyB2ZXJ0ZXg9XCZxdW90OzFcJnF1b3Q7Jmd0OyZsdDtteEdlb21ldHJ5IHg9XCZxdW90OzM2NVwmcXVvdDsgeT1cJnF1b3Q7MzIwXCZxdW90OyB3aWR0aD1cJnF1b3Q7MTIwXCZxdW90OyBoZWlnaHQ9XCZxdW90OzYwXCZxdW90OyBhcz1cJnF1b3Q7Z2VvbWV0cnlcJnF1b3Q7LyZndDsmbHQ7L214Q2VsbCZndDsmbHQ7bXhDZWxsIGlkPVwmcXVvdDsxMFwmcXVvdDsgdmFsdWU9XCZxdW90O1NpIG9uIGEgYmVzb2luIGRlIElEK0ZJTElFUkUgcG91ciBpZGVudGlmaWVyIGxlcyBsaWduZXMsIG9uIHZhIGV4Y2x1cmUgbGVzIGxpZ25lcyBvw7kgbGEgdmFsZXVyICZhbXA7cXVvdDtmaWxpw6hyZSZhbXA7cXVvdDsgbiYjMzk7ZXN0IHBhcyByZWluc2VpZ27DqWUgKG49OSlcJnF1b3Q7IHN0eWxlPVwmcXVvdDtlZGdlU3R5bGU9bm9uZTtodG1sPTE7XCZxdW90OyBwYXJlbnQ9XCZxdW90OzFcJnF1b3Q7IHNvdXJjZT1cJnF1b3Q7N1wmcXVvdDsgdGFyZ2V0PVwmcXVvdDs5XCZxdW90OyBlZGdlPVwmcXVvdDsxXCZxdW90OyZndDsmbHQ7bXhHZW9tZXRyeSByZWxhdGl2ZT1cJnF1b3Q7MVwmcXVvdDsgYXM9XCZxdW90O2dlb21ldHJ5XCZxdW90Oy8mZ3Q7Jmx0Oy9teENlbGwmZ3Q7Jmx0O214Q2VsbCBpZD1cJnF1b3Q7N1wmcXVvdDsgdmFsdWU9XCZxdW90Ozc3NiBxdWVzdGlvbm5haXJlc1wmcXVvdDsgc3R5bGU9XCZxdW90O3doaXRlU3BhY2U9d3JhcDtodG1sPTE7cm91bmRlZD0xO1wmcXVvdDsgcGFyZW50PVwmcXVvdDsxXCZxdW90OyB2ZXJ0ZXg9XCZxdW90OzFcJnF1b3Q7Jmd0OyZsdDtteEdlb21ldHJ5IHg9XCZxdW90OzM2NVwmcXVvdDsgeT1cJnF1b3Q7NDYwXCZxdW90OyB3aWR0aD1cJnF1b3Q7MTIwXCZxdW90OyBoZWlnaHQ9XCZxdW90OzYwXCZxdW90OyBhcz1cJnF1b3Q7Z2VvbWV0cnlcJnF1b3Q7LyZndDsmbHQ7L214Q2VsbCZndDsmbHQ7bXhDZWxsIGlkPVwmcXVvdDs5XCZxdW90OyB2YWx1ZT1cJnF1b3Q7NzY3IHF1ZXN0aW9ubmFpcmVzJmFtcDtsdDticiZhbXA7Z3Q7NDEzIGlkZW50aXTDqXMgdW5pcXVlcyBkb25uw6llcyBwYXIgSUQrRklMSUVSRVwmcXVvdDsgc3R5bGU9XCZxdW90O3doaXRlU3BhY2U9d3JhcDtodG1sPTE7cm91bmRlZD0xO1wmcXVvdDsgcGFyZW50PVwmcXVvdDsxXCZxdW90OyB2ZXJ0ZXg9XCZxdW90OzFcJnF1b3Q7Jmd0OyZsdDtteEdlb21ldHJ5IHg9XCZxdW90OzIzMFwmcXVvdDsgeT1cJnF1b3Q7NjAwXCZxdW90OyB3aWR0aD1cJnF1b3Q7MzkwXCZxdW90OyBoZWlnaHQ9XCZxdW90OzYwXCZxdW90OyBhcz1cJnF1b3Q7Z2VvbWV0cnlcJnF1b3Q7LyZndDsmbHQ7L214Q2VsbCZndDsmbHQ7L3Jvb3QmZ3Q7Jmx0Oy9teEdyYXBoTW9kZWwmZ3Q7Jmx0Oy9kaWFncmFtJmd0OyZsdDsvbXhmaWxlJmd0OyZxdW90O30iPjwvZGl2Pg0KPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiIHNyYz0iaHR0cHM6Ly92aWV3ZXIuZGlhZ3JhbXMubmV0L2pzL3ZpZXdlci1zdGF0aWMubWluLmpzIj48L3NjcmlwdD4NCg0KIyMgTmIgZXQgcmVwYXJ0aXRpb24gc3VqZXRzIHBhcnRpY2lwYW50cw0KYGBge3IgfQ0KDQpkYXRhICU+JSBkaXN0aW5jdChpZCxmaWxpZXJlKSAlJCUgDQogICAgdGFibGUoZmlsaWVyZSkgJT4lIA0KICAgIGFzLmRhdGEuZnJhbWUoKSAlPiUgDQogICAgbXV0YXRlKCIlIiA9IHJvdW5kKEZyZXEvc3VtKEZyZXEpKjEwMCwgMikpICU+JSANCiAgICBhZG9ybl90b3RhbHMoKSAlPiUgDQogICAgcGFuZGVyKGNhcHRpb24gPSAiKipSZXBhcnRpdGlvbiBzdWpldHMgcGFyIGZpbGnDqHJlKioiKQ0KYGBgDQo8YnI+DQoNCiMjIE1pc3NpbmcgdmFsdWVzDQoNClZveW9ucyBzdXIgdG91dCBsJ2Vuc2VtYmxlIGRlIHRlc3RzLCBjb21iaWVuIGRlIGRvbm7DqWVzIG1hbnF1YW50ZXMgb24gYS4gQ2Ugc29udCBkZXMgInZyYWllcyIgZG9ubsOpZXMgbWFucXVhbnRlcyAqKk9VKiogZGVzICJOU1AiIHF1aSBuJ8OpdGFpdCBwYXMgcGVydGluZW50cyBwb3VyIGxhIHF1ZXN0aW9uIGV0IHZyYWlzZW1ibGFibGVtZW50IHByaXMgcG91ciBkZXMgIk5lIHNhaXQgcGFzIi4NCg0KYGBge3IgbWlzc2luZyB2YWx1ZXN9DQoNCg0KdGFibGUoZGF0YSRuYV9jb3VudHMpICU+JSANCiAgICBhcy5kYXRhLmZyYW1lKCkgJT4lIA0KICAgIG11dGF0ZSgiJSIgPSByb3VuZChGcmVxL3N1bShGcmVxKSoxMDAsIDIpKSAlPiUgDQogICAgcmVuYW1lKCJOYiBtaXNzaW5nIHZhbHVlcyIgPSBWYXIxKSAlPiUgDQogICAgcGFuZGVyKGNhcHRpb24gPSAiKipOYiBkZSB2YWxldXJzIG1hbnF1YW50ZXMgcGFyIHF1ZXN0aW9ubmFpcmUqKiIpDQoNCmBgYA0KDQpPbiB2b2l0IHF1ZSBsZXMgdGVzdHMgc29udCBiaWVuIGNvbXBsZXRzIGdsb2JhbGVtZW50IHNhdWYgMTYgcXVlc3Rpb25uYWlyZXMgcXVpIHNvbnQgKipjb21wbMOpdGVtZW50KiogdmlkZXMuIElscyBzb250IGRlcyBkb3VibG9ucyBkdXMgw6AgZGVzIGVucmVnaXN0cmVtZW50cyB2aWRlcy4NCg0KPGJyPg0KDQo8YnI+DQoNCiMjIyBNaXNzaW5nIHZhbHVlcyBwYXIgZmlsacOocmUNCg0KT24gcGV1dCB2b2lyIHF1ZSBsYSByZXBhcnRpdGlvbiBkZXMgdmFsZXVycyBtYW5xdWFudGVzIHBhciBmaWxpw6hyZSBlc3QgZW4gbGlnbmUgYXZlYyBsYSByZXBhcnRpdGlvbiBkZXMgc3VqZXRzIHBhciBmaWxpw6hyZS4gRG9uYyBpbCBuJ3kgYSBwYXMgdW5lIGZpbGnDqHJlIHF1aSBhIGxhaXNzw6kgbGUgcXVlc3Rpb25uYWlyZSAicGx1cyB2aWRlIiBxdWUgbGVzIGF1dHJlcy4NCg0KYGBge3J9DQpkYXRhICU+JQ0KICBncm91cF9ieShmaWxpZXJlKSAlPiUNCiAgc3VtbWFyaXNlKEZyZXEgPSBzdW0obmFfY291bnRzKSkgJT4lDQogIG11dGF0ZSgiJSIgPSByb3VuZChGcmVxIC8gc3VtKEZyZXEpICogMTAwLCAyKSkgJT4lDQogICAgYWRvcm5fdG90YWxzKCkgJT4lIA0KICBwYW5kZXIoY2FwdGlvbiA9ICIqKlZhbGV1cnMgbWFucXVhbnRlcyBwYXIgZmlsacOocmUqKiIsIGFsaWduID0gImNlbnRlciIpDQoNCg0KYGBgDQoNCioqISEhISEhKiogUXVlbHF1ZSBjaG9zZSBuZSB2YSBwYXMsIG9uIGEgMzc5IHN1amV0cyBldCA4MDArIHF1ZXN0aW9ubmFpcmVzIChvbiBkZXZyYWl0IGVuIGF2b2lyICoqYXUgbWF4KiogMzc5XCoyKS4gRGFucyBsZSB0YWJsZWF1IHN1aXZhbnQgb24gdm9pdCBxdSdvbiBhIDE5OSBzdWpldHMgYXZlYyAqKmF1IG1vaW5zKiogMyBlbnRyw6llcyAoZXQgaidhaSBkw6lqw6AgZXhjbHUgbGVzIDE2IGRvbnQgamUgcGFybGFpcyBhdmFudCkuDQoNCmBgYHtyIG1lc3NhZ2UgPSBGfQ0KeCA8LSBkYXRhICU+JQ0KICBncm91cF9ieShpZCwgZmlsaWVyZSkgJT4lDQogIHN1bW1hcmlzZShuID0gbigpKSAlPiUNCiAgYXJyYW5nZShkZXNjKG4pKSAlPiUNCiAgZmlsdGVyKG4gPiAyKSAlPiUNCiAgcHVsbChpZCkgDQoNCmRhdGEgJT4lDQogICAgZmlsdGVyKGlkICVpbiUgeCkgJT4lDQogICAgYXJyYW5nZShpZCwgZmlsaWVyZSwgdGVzdCkgJT4lDQogICAgZGF0YXRhYmxlKG9wdGlvbnMgPSBsaXN0KHBhZ2VMZW5ndGggPSAxMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI2RvbSA9ICd0JywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2Nyb2xsWCA9IFRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoID0gImF1dG8iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY3JvbGxYID0gVA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICApDQogICAgICAgICAgICAgICkgDQpgYGANCg0KTGVzIGVudHLDqWVzIHN1cHBsZW1lbnRhaXJlcyBuZSBzb250IHBhcyBkZXMgImRvdWJsb25zIiwgbGVzIHZhbGV1cnMgbmUgc29udCBwYXMgbGVzIG3Dqm1lcy4gSmUgdmFpcyBkb25jIHByZW5kcmUgbGEgbW95ZW5uZSBkZSBjZXMgdmFsZXVycy4gQ2kgZGVzc291cyBsZSByw6lzdWx0YXQsIG9uIGVzdCDDoCA3NjYgbGlnbmVzIGFsb3IgcXVlIG5vdHJlIG1heCB0aGVvcmlxdWUgZXN0IDc1OC4gSWwgeSBhIGZvcmNlbWVudCBkZXMgZ2VucyBxdWkgc2Ugc29udCBlbnJlZ2lzdHLDqXMgYXZlYyBwbHVzIHF1J3VuIElEIChqJ2FpIHJlbm9tbcOpIGxhIHZhcmlhYmxlICJBMSIpLiAgIA0KQ2EgbmUgbSdpbnF1acOodGUgcGFzIHBvdXIgbGVzIHRlc3RzIGFwcGFyacOpcywgamUgbmUgcGVuc2UgcGFzIHF1ZSBkZXMgZ2VucyBvbnQgMioyIHRlc3RzIGFwcGFyacOpcyBtYWlzIGplIGNvbnRyb2xsZXJhaS4NCg0KYGBge3J9DQpkYXRhICU+JSANCiAgICBncm91cF9ieShpZCx0ZXN0LGZpbGllcmUpICU+JSANCiAgICBzdW1tYXJpc2UoYWNyb3NzKHMxcTE6czdxMixtZWFuLG5hLnJtPVQpKSAlPiUgDQogICAgbXV0YXRlKG5hX2NvdW50cyA9IHJvd1N1bXMoYWNyb3NzKHMxcTE6czdxMiwgaXMubmEpKSkgJT4lIA0KICAgIGRhdGF0YWJsZShvcHRpb25zID0gbGlzdChwYWdlTGVuZ3RoID0gMTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICNkb20gPSAndCcsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjcm9sbFggPSBUUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aCA9ICJhdXRvIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2Nyb2xsWCA9IFQNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQ0KICAgICAgICAgICAgICApDQpgYGANCg0KPGJyPg0KDQo8YnI+DQoNCiMgVGVzdHMgYXBwYXJpw6lzDQoNCmBgYHtyIENhcyBhcHBhcmnDqXMgcGFyIGZpbGnDqHJlfQ0KIyBERiB3aXRoIGlkLWZpbGllcmUtcHJlLXBvc3QgcG91ciBsZXMgdGVzdHMgc3RhdA0KdGVzdF9kYXRhIDwtIGRhdGEgJT4lDQogIGdyb3VwX2J5KGlkLCBmaWxpZXJlLCB0ZXN0KSAlPiUNCiAgc3VtbWFyaXNlKG1lYW5fc2NvcmUgPSBtZWFuKGNfYWNyb3NzKHMxcTE6czdxMiksIG5hLnJtID0gVCkpICU+JQ0KICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gInRlc3QiLCB2YWx1ZXNfZnJvbSA9ICJtZWFuX3Njb3JlIikgJT4lDQogICAgZmlsdGVyKCFpcy5uYShwb3N0KSwhaXMubmEocHJlKSkgJT4lIGRpc3RpbmN0DQoNCiMgcGFpcmVkIGNhc2VzIGJ5IGZpbGllcmUNCnRlc3RfZGF0YSAlJCUgDQogICAgdGFibGUoZmlsaWVyZSkgJT4lIA0KICAgIGFzLmRhdGEuZnJhbWUoKSAlPiUgDQogICAgbXV0YXRlKCIlIiA9IHJvdW5kKEZyZXEvc3VtKEZyZXEpKjEwMCwgMikpICU+JSANCiAgICBhZG9ybl90b3RhbHMoKSAlPiUgDQogICAgcGFuZGVyKGNhcHRpb24gPSAiQ2FzIGFwcGFyacOpcyBwYXIgZmlsacOocmUiKQ0KYGBgDQoNClBvdXIgY2VzIHBvdXJjZW50YWdlcyBsZXMgZGVub21pbmF0ZXVyIGVzdCAidG90YWwgZGUgdGVzdHMgYXBwYXJpw6lzIiBldCBub24gbGUgIm5vbWJyZSB0b3RhbCBkZSB0ZXN0cy4gRG9uYywgbGVzIElERSwgcmVwcmVzZW50ZW50IDM4LjE0JSBkZXMgdGVzdHMgYXBwYXJpw6lzIGRpc3BvbmlibGVzLg0KDQpNYWlzLCBpbCB5IGEgY2FycmVtZW50IHBsdXMgZCdJREUgcXVlIGxlcyBhdXRyZXMgZmlsacOocmVzISBPdWksIGJpZW4gc3VyLiBWb3lvbnMNCg0KIyBUZXN0cyBzdGF0DQoNCmBgYHtyIGFuYWx5c2lzfQ0KIyBQUkUgdnMgUE9TVCwgdG91dGVzIGZpbGllcmVzIGNvbmZvbmR1ZXMNCnQudGVzdCh0ZXN0X2RhdGEkcG9zdCx0ZXN0X2RhdGEkcHJlLCBwYWlyZWQ9VCkNCg0KIyBQUkUgdnMgUE9TVCwgZmlsaWVyZSBwYXIgZmlsaWVyZSANCnQudGVzdCh0ZXN0X2RhdGEkcG9zdFt0ZXN0X2RhdGEkZmlsaWVyZT09IklERSJdLHRlc3RfZGF0YSRwcmVbdGVzdF9kYXRhJGZpbGllcmU9PSJJREUiXSwgcGFpcmVkPVQpDQoNCmBgYA0K